/*
 * Copyright 2002-2019 the original author or authors.
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *      https://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

package org.springframework.beans.factory.support;

import org.apache.commons.logging.Log;
import org.springframework.beans.*;
import org.springframework.beans.factory.*;
import org.springframework.beans.factory.config.*;
import org.springframework.core.*;
import org.springframework.lang.Nullable;
import org.springframework.util.*;

import java.beans.PropertyDescriptor;
import java.lang.reflect.Constructor;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
import java.lang.reflect.Modifier;
import java.security.AccessController;
import java.security.PrivilegedAction;
import java.security.PrivilegedActionException;
import java.security.PrivilegedExceptionAction;
import java.util.*;
import java.util.concurrent.ConcurrentHashMap;
import java.util.concurrent.ConcurrentMap;
import java.util.function.Supplier;

/**
 * Abstract bean factory superclass that implements default bean creation,
 * with the full capabilities specified by the {@link RootBeanDefinition} class.
 * Implements the {@link org.springframework.beans.factory.config.AutowireCapableBeanFactory}
 * interface in addition to AbstractBeanFactory's {@link #createBean} method.
 *
 * <p>Provides bean creation (with constructor resolution), property population,
 * wiring (including autowiring), and initialization. Handles runtime bean
 * references, resolves managed collections, calls initialization methods, etc.
 * Supports autowiring constructors, properties by name, and properties by type.
 *
 * <p>The main template method to be implemented by subclasses is
 * {@link #resolveDependency(DependencyDescriptor, String, Set, TypeConverter)},
 * used for autowiring by type. In case of a factory which is capable of searching
 * its bean definitions, matching beans will typically be implemented through such
 * a search. For other factory styles, simplified matching algorithms can be implemented.
 *
 * <p>Note that this class does <i>not</i> assume or implement bean definition
 * registry capabilities. See {@link DefaultListableBeanFactory} for an implementation
 * of the {@link org.springframework.beans.factory.ListableBeanFactory} and
 * {@link BeanDefinitionRegistry} interfaces, which represent the API and SPI
 * view of such a factory, respectively.
 *
 * @author Rod Johnson
 * @author Juergen Hoeller
 * @author Rob Harrop
 * @author Mark Fisher
 * @author Costin Leau
 * @author Chris Beams
 * @author Sam Brannen
 * @see RootBeanDefinition
 * @see DefaultListableBeanFactory
 * @see BeanDefinitionRegistry
 * @since 13.02.2004
 */
public abstract class AbstractAutowireCapableBeanFactory extends AbstractBeanFactory
		implements AutowireCapableBeanFactory {

	/**
	 * Strategy for creating bean instances
	 */
	private InstantiationStrategy instantiationStrategy = new CglibSubclassingInstantiationStrategy();

	/**
	 * Resolver strategy for method parameter names
	 */
	@Nullable
	private ParameterNameDiscoverer parameterNameDiscoverer = new DefaultParameterNameDiscoverer();

	/**
	 * Whether to automatically try to resolve circular references between beans
	 */
	private boolean allowCircularReferences = true;

	/**
	 * Whether to resort to injecting a raw bean instance in case of circular reference,
	 * even if the injected bean eventually got wrapped.
	 */
	private boolean allowRawInjectionDespiteWrapping = false;

	/**
	 * Dependency types to ignore on dependency check and autowire, as Set of
	 * Class objects: for example, String. Default is none.
	 */
	private final Set<Class<?>> ignoredDependencyTypes = new HashSet<>();

	/**
	 * Dependency interfaces to ignore on dependency check and autowire, as Set of
	 * Class objects. By default, only the BeanFactory interface is ignored.
	 */
	private final Set<Class<?>> ignoredDependencyInterfaces = new HashSet<>();

	/**
	 * The name of the currently created bean, for implicit dependency registration
	 * on getBean etc invocations triggered from a user-specified Supplier callback.
	 */
	private final NamedThreadLocal<String> currentlyCreatedBean = new NamedThreadLocal<>( "Currently created bean" );

	/**
	 * Cache of unfinished FactoryBean instances: FactoryBean name to BeanWrapper
	 */
	private final ConcurrentMap<String, BeanWrapper> factoryBeanInstanceCache = new ConcurrentHashMap<>( 16 );

	/**
	 * Cache of filtered PropertyDescriptors: bean Class to PropertyDescriptor array
	 */
	private final ConcurrentMap<Class<?>, PropertyDescriptor[]> filteredPropertyDescriptorsCache =
			new ConcurrentHashMap<>( 256 );


	/**
	 * Create a new AbstractAutowireCapableBeanFactory.
	 */
	public AbstractAutowireCapableBeanFactory() {
		super();
		ignoreDependencyInterface( BeanNameAware.class );
		ignoreDependencyInterface( BeanFactoryAware.class );
		ignoreDependencyInterface( BeanClassLoaderAware.class );
	}

	/**
	 * Create a new AbstractAutowireCapableBeanFactory with the given parent.
	 *
	 * @param parentBeanFactory parent bean factory, or {@code null} if none
	 */
	public AbstractAutowireCapableBeanFactory(@Nullable BeanFactory parentBeanFactory) {
		this();
		setParentBeanFactory( parentBeanFactory );
	}


	/**
	 * Set the instantiation strategy to use for creating bean instances.
	 * Default is CglibSubclassingInstantiationStrategy.
	 *
	 * @see CglibSubclassingInstantiationStrategy
	 */
	public void setInstantiationStrategy(InstantiationStrategy instantiationStrategy) {
		this.instantiationStrategy = instantiationStrategy;
	}

	/**
	 * Return the instantiation strategy to use for creating bean instances.
	 */
	protected InstantiationStrategy getInstantiationStrategy() {
		return this.instantiationStrategy;
	}

	/**
	 * Set the ParameterNameDiscoverer to use for resolving method parameter
	 * names if needed (e.g. for constructor names).
	 * <p>Default is a {@link DefaultParameterNameDiscoverer}.
	 */
	public void setParameterNameDiscoverer(@Nullable ParameterNameDiscoverer parameterNameDiscoverer) {
		this.parameterNameDiscoverer = parameterNameDiscoverer;
	}

	/**
	 * Return the ParameterNameDiscoverer to use for resolving method parameter
	 * names if needed.
	 */
	@Nullable
	protected ParameterNameDiscoverer getParameterNameDiscoverer() {
		return this.parameterNameDiscoverer;
	}

	/**
	 * Set whether to allow circular references between beans - and automatically
	 * try to resolve them.
	 * <p>Note that circular reference resolution means that one of the involved beans
	 * will receive a reference to another bean that is not fully initialized yet.
	 * This can lead to subtle and not-so-subtle side effects on initialization;
	 * it does work fine for many scenarios, though.
	 * <p>Default is "true". Turn this off to throw an exception when encountering
	 * a circular reference, disallowing them completely.
	 * <p><b>NOTE:</b> It is generally recommended to not rely on circular references
	 * between your beans. Refactor your application logic to have the two beans
	 * involved delegate to a third bean that encapsulates their common logic.
	 */
	public void setAllowCircularReferences(boolean allowCircularReferences) {
		this.allowCircularReferences = allowCircularReferences;
	}

	/**
	 * Set whether to allow the raw injection of a bean instance into some other
	 * bean's property, despite the injected bean eventually getting wrapped
	 * (for example, through AOP auto-proxying).
	 * <p>This will only be used as a last resort in case of a circular reference
	 * that cannot be resolved otherwise: essentially, preferring a raw instance
	 * getting injected over a failure of the entire bean wiring process.
	 * <p>Default is "false", as of Spring 2.0. Turn this on to allow for non-wrapped
	 * raw beans injected into some of your references, which was Spring 1.2's
	 * (arguably unclean) default behavior.
	 * <p><b>NOTE:</b> It is generally recommended to not rely on circular references
	 * between your beans, in particular with auto-proxying involved.
	 *
	 * @see #setAllowCircularReferences
	 */
	public void setAllowRawInjectionDespiteWrapping(boolean allowRawInjectionDespiteWrapping) {
		this.allowRawInjectionDespiteWrapping = allowRawInjectionDespiteWrapping;
	}

	/**
	 * Ignore the given dependency type for autowiring:
	 * for example, String. Default is none.
	 */
	public void ignoreDependencyType(Class<?> type) {
		this.ignoredDependencyTypes.add( type );
	}

	/**
	 * Ignore the given dependency interface for autowiring.
	 * <p>This will typically be used by application contexts to register
	 * dependencies that are resolved in other ways, like BeanFactory through
	 * BeanFactoryAware or ApplicationContext through ApplicationContextAware.
	 * <p>By default, only the BeanFactoryAware interface is ignored.
	 * For further types to ignore, invoke this method for each type.
	 *
	 * @see org.springframework.beans.factory.BeanFactoryAware
	 * @see org.springframework.context.ApplicationContextAware
	 */
	public void ignoreDependencyInterface(Class<?> ifc) {
		this.ignoredDependencyInterfaces.add( ifc );
	}

	@Override
	public void copyConfigurationFrom(ConfigurableBeanFactory otherFactory) {
		super.copyConfigurationFrom( otherFactory );
		if (otherFactory instanceof AbstractAutowireCapableBeanFactory) {
			AbstractAutowireCapableBeanFactory otherAutowireFactory =
					(AbstractAutowireCapableBeanFactory) otherFactory;
			this.instantiationStrategy = otherAutowireFactory.instantiationStrategy;
			this.allowCircularReferences = otherAutowireFactory.allowCircularReferences;
			this.ignoredDependencyTypes.addAll( otherAutowireFactory.ignoredDependencyTypes );
			this.ignoredDependencyInterfaces.addAll( otherAutowireFactory.ignoredDependencyInterfaces );
		}
	}


	//-------------------------------------------------------------------------
	// Typical methods for creating and populating external bean instances
	//-------------------------------------------------------------------------

	@Override
	@SuppressWarnings("unchecked")
	public <T> T createBean(Class<T> beanClass) throws BeansException {
		// Use prototype bean definition, to avoid registering bean as dependent bean.
		RootBeanDefinition bd = new RootBeanDefinition( beanClass );
		bd.setScope( SCOPE_PROTOTYPE );
		bd.allowCaching = ClassUtils.isCacheSafe( beanClass, getBeanClassLoader() );
		return (T) createBean( beanClass.getName(), bd, null );
	}

	@Override
	public void autowireBean(Object existingBean) {
		// Use non-singleton bean definition, to avoid registering bean as dependent bean.
		RootBeanDefinition bd = new RootBeanDefinition( ClassUtils.getUserClass( existingBean ) );
		bd.setScope( BeanDefinition.SCOPE_PROTOTYPE );
		bd.allowCaching = ClassUtils.isCacheSafe( bd.getBeanClass(), getBeanClassLoader() );
		BeanWrapper bw = new BeanWrapperImpl( existingBean );
		initBeanWrapper( bw );
		populateBean( bd.getBeanClass().getName(), bd, bw );
	}

	@Override
	public Object configureBean(Object existingBean, String beanName) throws BeansException {
		markBeanAsCreated( beanName );
		BeanDefinition mbd = getMergedBeanDefinition( beanName );
		RootBeanDefinition bd = null;
		if (mbd instanceof RootBeanDefinition) {
			RootBeanDefinition rbd = (RootBeanDefinition) mbd;
			bd = (rbd.isPrototype() ? rbd : rbd.cloneBeanDefinition());
		}
		if (bd == null) {
			bd = new RootBeanDefinition( mbd );
		}
		if (!bd.isPrototype()) {
			bd.setScope( BeanDefinition.SCOPE_PROTOTYPE );
			bd.allowCaching = ClassUtils.isCacheSafe( ClassUtils.getUserClass( existingBean ), getBeanClassLoader() );
		}
		BeanWrapper bw = new BeanWrapperImpl( existingBean );
		initBeanWrapper( bw );
		populateBean( beanName, bd, bw );
		return initializeBean( beanName, existingBean, bd );
	}

	@Override
	@Nullable
	public Object resolveDependency(DependencyDescriptor descriptor, @Nullable String requestingBeanName) throws BeansException {
		return resolveDependency( descriptor, requestingBeanName, null, null );
	}


	//-------------------------------------------------------------------------
	// Specialized methods for fine-grained control over the bean lifecycle
	//-------------------------------------------------------------------------

	@Override
	public Object createBean(Class<?> beanClass, int autowireMode, boolean dependencyCheck) throws BeansException {
		// Use non-singleton bean definition, to avoid registering bean as dependent bean.
		RootBeanDefinition bd = new RootBeanDefinition( beanClass, autowireMode, dependencyCheck );
		bd.setScope( BeanDefinition.SCOPE_PROTOTYPE );
		return createBean( beanClass.getName(), bd, null );
	}

	@Override
	public Object autowire(Class<?> beanClass, int autowireMode, boolean dependencyCheck) throws BeansException {
		// Use non-singleton bean definition, to avoid registering bean as dependent bean.
		final RootBeanDefinition bd = new RootBeanDefinition( beanClass, autowireMode, dependencyCheck );
		bd.setScope( BeanDefinition.SCOPE_PROTOTYPE );
		//自动注入方式是构造器注入
		if (bd.getResolvedAutowireMode() == AUTOWIRE_CONSTRUCTOR) {
			return autowireConstructor( beanClass.getName(), bd, null, null ).getWrappedInstance();
		} else {
			Object bean;
			final BeanFactory parent = this;
			if (System.getSecurityManager() != null) {
				bean = AccessController.doPrivileged( (PrivilegedAction<Object>) () ->
								getInstantiationStrategy().instantiate( bd, null, parent ),
						getAccessControlContext() );
			} else {
				bean = getInstantiationStrategy().instantiate( bd, null, parent );
			}
			populateBean( beanClass.getName(), bd, new BeanWrapperImpl( bean ) );
			return bean;
		}
	}

	@Override
	public void autowireBeanProperties(Object existingBean, int autowireMode, boolean dependencyCheck)
			throws BeansException {

		if (autowireMode == AUTOWIRE_CONSTRUCTOR) {
			throw new IllegalArgumentException( "AUTOWIRE_CONSTRUCTOR not supported for existing bean instance" );
		}
		// Use non-singleton bean definition, to avoid registering bean as dependent bean.
		RootBeanDefinition bd =
				new RootBeanDefinition( ClassUtils.getUserClass( existingBean ), autowireMode, dependencyCheck );
		bd.setScope( BeanDefinition.SCOPE_PROTOTYPE );
		BeanWrapper bw = new BeanWrapperImpl( existingBean );
		initBeanWrapper( bw );
		populateBean( bd.getBeanClass().getName(), bd, bw );
	}

	@Override
	public void applyBeanPropertyValues(Object existingBean, String beanName) throws BeansException {
		markBeanAsCreated( beanName );
		BeanDefinition bd = getMergedBeanDefinition( beanName );
		BeanWrapper bw = new BeanWrapperImpl( existingBean );
		initBeanWrapper( bw );
		applyPropertyValues( beanName, bd, bw, bd.getPropertyValues() );
	}

	@Override
	public Object initializeBean(Object existingBean, String beanName) {
		return initializeBean( beanName, existingBean, null );
	}

	@Override
	public Object applyBeanPostProcessorsBeforeInitialization(Object existingBean, String beanName)
			throws BeansException {

		Object result = existingBean;
		for (BeanPostProcessor processor : getBeanPostProcessors()) {
			//执行所有Bean后置处理器的postProcessBeforeInitialization方法
			Object current = processor.postProcessBeforeInitialization( result, beanName );
			if (current == null) {
				return result;
			}
			result = current;
		}
		return result;
	}

	@Override
	public Object applyBeanPostProcessorsAfterInitialization(Object existingBean, String beanName)
			throws BeansException {

		Object result = existingBean;
		for (BeanPostProcessor processor : getBeanPostProcessors()) {
			Object current = processor.postProcessAfterInitialization( result, beanName );
			if (current == null) {
				return result;
			}
			result = current;
		}
		return result;
	}

	@Override
	public void destroyBean(Object existingBean) {
		new DisposableBeanAdapter( existingBean, getBeanPostProcessors(), getAccessControlContext() ).destroy();
	}


	//---------------------------------------------------------------------
	// Implementation of relevant AbstractBeanFactory template methods
	//---------------------------------------------------------------------

	/**
	 * 创建bean实例,本类中的核心方法。完成bean实例的属性填充、应用后置处理器等
	 * Central method of this class: creates a bean instance,
	 * populates the bean instance, applies post-processors, etc.
	 *
	 * @see #doCreateBean
	 */
	@Override
	protected Object createBean(String beanName, RootBeanDefinition mbd, @Nullable Object[] args)
			throws BeanCreationException {

		if (logger.isDebugEnabled()) {
			logger.debug( "Creating instance of bean '" + beanName + "'" );
		}
		//需要创建的bean的BeanDefinition
		RootBeanDefinition mbdToUse = mbd;

		// Make sure bean class is actually resolved at this point, and
		// clone the bean definition in case of a dynamically resolved Class
		// which cannot be stored in the shared merged bean definition.
		Class<?> resolvedClass = resolveBeanClass( mbd, beanName );
		if (resolvedClass != null && !mbd.hasBeanClass() && mbd.getBeanClassName() != null) {
			mbdToUse = new RootBeanDefinition( mbd );
			mbdToUse.setBeanClass( resolvedClass );
		}

		// Prepare method overrides.
		//准备方法重写
		try {
			/**
			 * 处理look-method和replace-method配置，Spring将这两个配置统称为重写
			 */
			mbdToUse.prepareMethodOverrides();
		} catch (BeanDefinitionValidationException ex) {
			throw new BeanDefinitionStoreException( mbdToUse.getResourceDescription(),
					beanName, "Validation of method overrides failed", ex );
		}

		try {
			/**
			 * Give BeanPostProcessors a chance to return a proxy instead of the target bean instance.
			 * Bean初始化前应用后置处理器，允许目标返回代理
			 */
			Object bean = resolveBeforeInstantiation( beanName, mbdToUse );
			if (bean != null) {
				return bean;
			}
		} catch (Throwable ex) {
			throw new BeanCreationException( mbdToUse.getResourceDescription(), beanName,
					"BeanPostProcessor before instantiation of bean failed", ex );
		}

		try {
			//创建Spring的Bean
			Object beanInstance = doCreateBean( beanName, mbdToUse, args );
			if (logger.isDebugEnabled()) {
				logger.debug( "Finished creating instance of bean '" + beanName + "'" );
			}
			return beanInstance;
		} catch (BeanCreationException | ImplicitlyAppearedSingletonException ex) {
			// A previously detected exception with proper bean creation context already,
			// or illegal singleton state to be communicated up to DefaultSingletonBeanRegistry.
			throw ex;
		} catch (Throwable ex) {
			throw new BeanCreationException(
					mbdToUse.getResourceDescription(), beanName, "Unexpected exception during bean creation", ex );
		}
	}

	/**
	 * Actually create the specified bean. Pre-creation processing has already happened
	 * at this point, e.g. checking {@code postProcessBeforeInstantiation} callbacks.
	 * <p>Differentiates between default bean instantiation, use of a
	 * factory method, and autowiring a constructor.
	 *
	 * @param beanName the name of the bean
	 * @param mbd      the merged bean definition for the bean
	 * @param args     explicit arguments to use for constructor or factory method invocation
	 * @return a new instance of the bean
	 * @throws BeanCreationException if the bean could not be created
	 * @see #instantiateBean
	 * @see #instantiateUsingFactoryMethod
	 * @see #autowireConstructor
	 */
	protected Object doCreateBean(final String beanName, final RootBeanDefinition mbd, final @Nullable Object[] args)
			throws BeanCreationException {

		// Instantiate the bean
		BeanWrapper instanceWrapper = null;
		if (mbd.isSingleton()) {
			instanceWrapper = this.factoryBeanInstanceCache.remove( beanName );
		}
		if (instanceWrapper == null) {
			//实例化对象
			instanceWrapper = createBeanInstance( beanName, mbd, args );
		}
		final Object bean = instanceWrapper.getWrappedInstance();
		Class<?> beanType = instanceWrapper.getWrappedClass();
		if (beanType != NullBean.class) {
			mbd.resolvedTargetType = beanType;
		}

		// Allow post-processors to modify the merged bean definition.
		//允许后置处理器修改合并后的BeanDefinition
		synchronized (mbd.postProcessingLock) {
			if (!mbd.postProcessed) {
				try {
					//在此处执行实现了 MergedBeanDefinitionPostProcessor接口的后置处理器
					applyMergedBeanDefinitionPostProcessors( mbd, beanType, beanName );
				} catch (Throwable ex) {
					throw new BeanCreationException( mbd.getResourceDescription(), beanName,
							"Post-processing of merged bean definition failed", ex );
				}
				mbd.postProcessed = true;
			}
		}

		// Eagerly cache singletons to be able to resolve circular references
		// even when triggered by lifecycle interfaces like BeanFactoryAware.    BeanFactoryAware？
		//单例&&允许循环依赖&&bean正在创建
		boolean earlySingletonExposure = (mbd.isSingleton() && this.allowCircularReferences &&
				isSingletonCurrentlyInCreation( beanName ));
		//在解决循环依赖过程中，把bean封装成工厂存放到singletonFactories这个Map中
		if (earlySingletonExposure) {
			if (logger.isDebugEnabled()) {
				logger.debug( "Eagerly caching bean '" + beanName +
						"' to allow for resolving potential circular references" );
			}
			/**
			 * 把创建好的对象添加到(早期曝光单例对象)单例工厂中（解决循环依赖）
			 * 获取早期Bean引用(执行SmartInstantiationAwareBeanPostProcessor后置处理器)
			 * 提前暴露自己的工厂，当前实例化对象 (bean) 封装成工厂,在封装的工厂中(使用策略模式可以对 bean 实例进行修改)
			 * 工厂中 getObject 方法返回的是实例化对象(getEarlyBeanReference 的方法参数   bean)
			 *	在工厂中可以进行进一步封装，如把原始bean对象编程代理对象，这也就是这里二级缓存中缓存的是工厂对象的原因
			 *  利用策略模式+工厂模式生成一个合格的bean
			 */
			addSingletonFactory( beanName, () -> getEarlyBeanReference( beanName, mbd, bean ) );
		}

		// Initialize the bean instance.
		//初始化bean实例
		Object exposedObject = bean;
		try {
			//bean属性填充(包括常说的自动注入就在这个方法中执行（解决循环依赖），注入的bean是当前创建bean的属性)
			populateBean( beanName, mbd, instanceWrapper );
			//bean初始化，并在bean初始化前后执行BeanPostProcessor方法
			exposedObject = initializeBean( beanName, exposedObject, mbd );
		} catch (Throwable ex) {
			if (ex instanceof BeanCreationException && beanName.equals( ((BeanCreationException) ex).getBeanName() )) {
				throw (BeanCreationException) ex;
			} else {
				throw new BeanCreationException(
						mbd.getResourceDescription(), beanName, "Initialization of bean failed", ex );
			}
		}

		//----------------------至此 bean已完成初始化操作  -------------------------
		if (earlySingletonExposure) {
			Object earlySingletonReference = getSingleton( beanName, false );
			if (earlySingletonReference != null) {
				if (exposedObject == bean) {//？？？？？
					exposedObject = earlySingletonReference;
				} else if (!this.allowRawInjectionDespiteWrapping && hasDependentBean( beanName )) {
					String[] dependentBeans = getDependentBeans( beanName );
					Set<String> actualDependentBeans = new LinkedHashSet<>( dependentBeans.length );
					for (String dependentBean : dependentBeans) {
						if (!removeSingletonIfCreatedForTypeCheckOnly( dependentBean )) {
							actualDependentBeans.add( dependentBean );
						}
					}
					if (!actualDependentBeans.isEmpty()) {
						throw new BeanCurrentlyInCreationException( beanName,
								"Bean with name '" + beanName + "' has been injected into other beans [" +
										StringUtils.collectionToCommaDelimitedString( actualDependentBeans ) +
										"] in its raw version as part of a circular reference, but has eventually been " +
										"wrapped. This means that said other beans do not use the final version of the " +
										"bean. This is often the result of over-eager type matching - consider using " +
										"'getBeanNamesOfType' with the 'allowEagerInit' flag turned off, for example." );
					}
				}
			}
		}

		// Register bean as disposable.
		try {
			registerDisposableBeanIfNecessary( beanName, bean, mbd );
		} catch (BeanDefinitionValidationException ex) {
			throw new BeanCreationException(
					mbd.getResourceDescription(), beanName, "Invalid destruction signature", ex );
		}

		return exposedObject;
	}

	@Override
	@Nullable
	//推断Bean的类型（Class）
	protected Class<?> predictBeanType(String beanName, RootBeanDefinition mbd, Class<?>... typesToMatch) {
		Class<?> targetType = determineTargetType( beanName, mbd, typesToMatch );
		// Apply SmartInstantiationAwareBeanPostProcessors to predict the
		// eventual type after a before-instantiation shortcut.
		if (targetType != null && !mbd.isSynthetic() && hasInstantiationAwareBeanPostProcessors()) {
			for (BeanPostProcessor bp : getBeanPostProcessors()) {
				if (bp instanceof SmartInstantiationAwareBeanPostProcessor) {
					SmartInstantiationAwareBeanPostProcessor ibp = (SmartInstantiationAwareBeanPostProcessor) bp;
					Class<?> predicted = ibp.predictBeanType( targetType, beanName );
					if (predicted != null && (typesToMatch.length != 1 || FactoryBean.class != typesToMatch[0] ||
							FactoryBean.class.isAssignableFrom( predicted ))) {
						return predicted;
					}
				}
			}
		}
		return targetType;
	}

	/**
	 * Determine the target type for the given bean definition.
	 *
	 * @param beanName     the name of the bean (for error handling purposes)
	 * @param mbd          the merged bean definition for the bean
	 * @param typesToMatch the types to match in case of internal type matching purposes
	 *                     (also signals that the returned {@code Class} will never be exposed to application code)
	 * @return the type for the bean if determinable, or {@code null} otherwise
	 * 推断目标类型
	 */
	@Nullable
	protected Class<?> determineTargetType(String beanName, RootBeanDefinition mbd, Class<?>... typesToMatch) {
		Class<?> targetType = mbd.getTargetType();
		if (targetType == null) {
			targetType = (mbd.getFactoryMethodName() != null ?
					getTypeForFactoryMethod( beanName, mbd, typesToMatch ) :
					resolveBeanClass( mbd, beanName, typesToMatch ));
			if (ObjectUtils.isEmpty( typesToMatch ) || getTempClassLoader() == null) {
				mbd.resolvedTargetType = targetType;
			}
		}
		return targetType;
	}

	/**
	 * Determine the target type for the given bean definition which is based on
	 * a factory method. Only called if there is no singleton instance registered
	 * for the target bean already.
	 * <p>This implementation determines the type matching {@link #createBean}'s
	 * different creation strategies. As far as possible, we'll perform static
	 * type checking to avoid creation of the target bean.
	 *
	 * @param beanName     the name of the bean (for error handling purposes)
	 * @param mbd          the merged bean definition for the bean
	 * @param typesToMatch the types to match in case of internal type matching purposes
	 *                     (also signals that the returned {@code Class} will never be exposed to application code)
	 * @return the type for the bean if determinable, or {@code null} otherwise
	 * @see #createBean
	 */
	@Nullable
	protected Class<?> getTypeForFactoryMethod(String beanName, RootBeanDefinition mbd, Class<?>... typesToMatch) {
		ResolvableType cachedReturnType = mbd.factoryMethodReturnType;
		if (cachedReturnType != null) {
			return cachedReturnType.resolve();
		}

		Class<?> factoryClass;
		boolean isStatic = true;

		String factoryBeanName = mbd.getFactoryBeanName();
		if (factoryBeanName != null) {
			if (factoryBeanName.equals( beanName )) {
				throw new BeanDefinitionStoreException( mbd.getResourceDescription(), beanName,
						"factory-bean reference points back to the same bean definition" );
			}
			// Check declared factory method return type on factory class.
			factoryClass = getType( factoryBeanName );
			isStatic = false;
		} else {
			// Check declared factory method return type on bean class.
			factoryClass = resolveBeanClass( mbd, beanName, typesToMatch );
		}

		if (factoryClass == null) {
			return null;
		}
		factoryClass = ClassUtils.getUserClass( factoryClass );

		// If all factory methods have the same return type, return that type.
		// Can't clearly figure out exact method due to type converting / autowiring!
		Class<?> commonType = null;
		Method uniqueCandidate = null;
		int minNrOfArgs =
				(mbd.hasConstructorArgumentValues() ? mbd.getConstructorArgumentValues().getArgumentCount() : 0);
		Method[] candidates = ReflectionUtils.getUniqueDeclaredMethods( factoryClass );
		for (Method candidate : candidates) {
			if (Modifier.isStatic( candidate.getModifiers() ) == isStatic && mbd.isFactoryMethod( candidate ) &&
					candidate.getParameterCount() >= minNrOfArgs) {
				// Declared type variables to inspect?
				if (candidate.getTypeParameters().length > 0) {
					try {
						// Fully resolve parameter names and argument values.
						Class<?>[] paramTypes = candidate.getParameterTypes();
						String[] paramNames = null;
						ParameterNameDiscoverer pnd = getParameterNameDiscoverer();
						if (pnd != null) {
							paramNames = pnd.getParameterNames( candidate );
						}
						ConstructorArgumentValues cav = mbd.getConstructorArgumentValues();
						Set<ConstructorArgumentValues.ValueHolder> usedValueHolders = new HashSet<>( paramTypes.length );
						Object[] args = new Object[paramTypes.length];
						for (int i = 0; i < args.length; i++) {
							ConstructorArgumentValues.ValueHolder valueHolder = cav.getArgumentValue(
									i, paramTypes[i], (paramNames != null ? paramNames[i] : null), usedValueHolders );
							if (valueHolder == null) {
								valueHolder = cav.getGenericArgumentValue( null, null, usedValueHolders );
							}
							if (valueHolder != null) {
								args[i] = valueHolder.getValue();
								usedValueHolders.add( valueHolder );
							}
						}
						Class<?> returnType = AutowireUtils.resolveReturnTypeForFactoryMethod(
								candidate, args, getBeanClassLoader() );
						uniqueCandidate = (commonType == null && returnType == candidate.getReturnType() ?
								candidate : null);
						commonType = ClassUtils.determineCommonAncestor( returnType, commonType );
						if (commonType == null) {
							// Ambiguous return types found: return null to indicate "not determinable".
							return null;
						}
					} catch (Throwable ex) {
						if (logger.isDebugEnabled()) {
							logger.debug( "Failed to resolve generic return type for factory method: " + ex );
						}
					}
				} else {
					uniqueCandidate = (commonType == null ? candidate : null);
					commonType = ClassUtils.determineCommonAncestor( candidate.getReturnType(), commonType );
					if (commonType == null) {
						// Ambiguous return types found: return null to indicate "not determinable".
						return null;
					}
				}
			}
		}

		if (commonType == null) {
			return null;
		}
		// Common return type found: all factory methods return same type. For a non-parameterized
		// unique candidate, cache the full type declaration context of the target factory method.
		cachedReturnType = (uniqueCandidate != null ?
				ResolvableType.forMethodReturnType( uniqueCandidate ) : ResolvableType.forClass( commonType ));
		mbd.factoryMethodReturnType = cachedReturnType;
		return cachedReturnType.resolve();
	}

	/**
	 * This implementation attempts to query the FactoryBean's generic parameter metadata
	 * if present to determine the object type. If not present, i.e. the FactoryBean is
	 * declared as a raw type, checks the FactoryBean's {@code getObjectType} method
	 * on a plain instance of the FactoryBean, without bean properties applied yet.
	 * If this doesn't return a type yet, a full creation of the FactoryBean is
	 * used as fallback (through delegation to the superclass's implementation).
	 * <p>The shortcut check for a FactoryBean is only applied in case of a singleton
	 * FactoryBean. If the FactoryBean instance itself is not kept as singleton,
	 * it will be fully created to check the type of its exposed object.
	 */
	@Override
	@Nullable
	protected Class<?> getTypeForFactoryBean(String beanName, RootBeanDefinition mbd) {
		String factoryBeanName = mbd.getFactoryBeanName();
		String factoryMethodName = mbd.getFactoryMethodName();

		if (factoryBeanName != null) {
			if (factoryMethodName != null) {
				// Try to obtain the FactoryBean's object type from its factory method declaration
				// without instantiating the containing bean at all.
				BeanDefinition fbDef = getBeanDefinition( factoryBeanName );
				if (fbDef instanceof AbstractBeanDefinition) {
					AbstractBeanDefinition afbDef = (AbstractBeanDefinition) fbDef;
					if (afbDef.hasBeanClass()) {
						Class<?> result = getTypeForFactoryBeanFromMethod( afbDef.getBeanClass(), factoryMethodName );
						if (result != null) {
							return result;
						}
					}
				}
			}
			// If not resolvable above and the referenced factory bean doesn't exist yet,
			// exit here - we don't want to force the creation of another bean just to
			// obtain a FactoryBean's object type...
			if (!isBeanEligibleForMetadataCaching( factoryBeanName )) {
				return null;
			}
		}

		// Let's obtain a shortcut instance for an early getObjectType() call...
		FactoryBean<?> fb = (mbd.isSingleton() ?
				getSingletonFactoryBeanForTypeCheck( beanName, mbd ) :
				getNonSingletonFactoryBeanForTypeCheck( beanName, mbd ));

		if (fb != null) {
			// Try to obtain the FactoryBean's object type from this early stage of the instance.
			Class<?> result = getTypeForFactoryBean( fb );
			if (result != null) {
				return result;
			} else {
				// No type found for shortcut FactoryBean instance:
				// fall back to full creation of the FactoryBean instance.
				return super.getTypeForFactoryBean( beanName, mbd );
			}
		}

		if (factoryBeanName == null && mbd.hasBeanClass()) {
			// No early bean instantiation possible: determine FactoryBean's type from
			// static factory method signature or from class inheritance hierarchy...
			if (factoryMethodName != null) {
				return getTypeForFactoryBeanFromMethod( mbd.getBeanClass(), factoryMethodName );
			} else {
				return GenericTypeResolver.resolveTypeArgument( mbd.getBeanClass(), FactoryBean.class );
			}
		}

		return null;
	}

	/**
	 * Introspect the factory method signatures on the given bean class,
	 * trying to find a common {@code FactoryBean} object type declared there.
	 *
	 * @param beanClass         the bean class to find the factory method on
	 * @param factoryMethodName the name of the factory method
	 * @return the common {@code FactoryBean} object type, or {@code null} if none
	 */
	@Nullable
	private Class<?> getTypeForFactoryBeanFromMethod(Class<?> beanClass, final String factoryMethodName) {
		class Holder {
			@Nullable
			Class<?> value = null;
		}
		final Holder objectType = new Holder();

		// CGLIB subclass methods hide generic parameters; look at the original user class.
		Class<?> fbClass = ClassUtils.getUserClass( beanClass );

		// Find the given factory method, taking into account that in the case of
		// @Bean methods, there may be parameters present.
		ReflectionUtils.doWithMethods( fbClass, method -> {
			if (method.getName().equals( factoryMethodName ) &&
					FactoryBean.class.isAssignableFrom( method.getReturnType() )) {
				Class<?> currentType = GenericTypeResolver.resolveReturnTypeArgument( method, FactoryBean.class );
				if (currentType != null) {
					objectType.value = ClassUtils.determineCommonAncestor( currentType, objectType.value );
				}
			}
		} );

		return (objectType.value != null && Object.class != objectType.value ? objectType.value : null);
	}

	/**
	 * Obtain a reference for early access to the specified bean,
	 * typically for the purpose of resolving a circular reference.
	 *
	 * @param beanName the name of the bean (for error handling purposes)
	 * @param mbd      the merged bean definition for the bean
	 * @param bean     the raw bean instance
	 * @return the object to expose as bean reference
	 */
	protected Object getEarlyBeanReference(String beanName, RootBeanDefinition mbd, Object bean) {
		Object exposedObject = bean;
		//非合成&&有InstantiationAwareBeanPostProcessors 实例化Aware后置处理器
		//在有InstantiationAwareBeanPostProcessors中处理bean(策略模式)
		if (!mbd.isSynthetic() && hasInstantiationAwareBeanPostProcessors()) {
			for (BeanPostProcessor bp : getBeanPostProcessors()) {
				//执行后置处理器SmartInstantiationAwareBeanPostProcessor
				if (bp instanceof SmartInstantiationAwareBeanPostProcessor) {
					SmartInstantiationAwareBeanPostProcessor ibp = (SmartInstantiationAwareBeanPostProcessor) bp;
					//使用代理
					//AbstractAutoProxyCreator 实现了SmartInstantiationAwareBeanPostProcessor接口，用于动态代理
					exposedObject = ibp.getEarlyBeanReference( exposedObject, beanName );
				}
			}
		}
		return exposedObject;
	}


	//---------------------------------------------------------------------
	// Implementation methods
	//---------------------------------------------------------------------

	/**
	 * Obtain a "shortcut" singleton FactoryBean instance to use for a
	 * {@code getObjectType()} call, without full initialization of the FactoryBean.
	 *
	 * @param beanName the name of the bean
	 * @param mbd      the bean definition for the bean
	 * @return the FactoryBean instance, or {@code null} to indicate
	 * that we couldn't obtain a shortcut FactoryBean instance
	 */
	@Nullable
	private FactoryBean<?> getSingletonFactoryBeanForTypeCheck(String beanName, RootBeanDefinition mbd) {
		synchronized (getSingletonMutex()) {
			BeanWrapper bw = this.factoryBeanInstanceCache.get( beanName );
			if (bw != null) {
				return (FactoryBean<?>) bw.getWrappedInstance();
			}
			Object beanInstance = getSingleton( beanName, false );
			if (beanInstance instanceof FactoryBean) {
				return (FactoryBean<?>) beanInstance;
			}
			if (isSingletonCurrentlyInCreation( beanName ) ||
					(mbd.getFactoryBeanName() != null && isSingletonCurrentlyInCreation( mbd.getFactoryBeanName() ))) {
				return null;
			}

			Object instance;
			try {
				// Mark this bean as currently in creation, even if just partially.
				beforeSingletonCreation( beanName );
				// Give BeanPostProcessors a chance to return a proxy instead of the target bean instance.
				instance = resolveBeforeInstantiation( beanName, mbd );
				if (instance == null) {
					bw = createBeanInstance( beanName, mbd, null );
					instance = bw.getWrappedInstance();
				}
			} finally {
				// Finished partial creation of this bean.
				afterSingletonCreation( beanName );
			}

			FactoryBean<?> fb = getFactoryBean( beanName, instance );
			if (bw != null) {
				this.factoryBeanInstanceCache.put( beanName, bw );
			}
			return fb;
		}
	}

	/**
	 * Obtain a "shortcut" non-singleton FactoryBean instance to use for a
	 * {@code getObjectType()} call, without full initialization of the FactoryBean.
	 *
	 * @param beanName the name of the bean
	 * @param mbd      the bean definition for the bean
	 * @return the FactoryBean instance, or {@code null} to indicate
	 * that we couldn't obtain a shortcut FactoryBean instance
	 */
	@Nullable
	private FactoryBean<?> getNonSingletonFactoryBeanForTypeCheck(String beanName, RootBeanDefinition mbd) {
		if (isPrototypeCurrentlyInCreation( beanName )) {
			return null;
		}

		Object instance;
		try {
			// Mark this bean as currently in creation, even if just partially.
			beforePrototypeCreation( beanName );
			// Give BeanPostProcessors a chance to return a proxy instead of the target bean instance.
			instance = resolveBeforeInstantiation( beanName, mbd );
			if (instance == null) {
				BeanWrapper bw = createBeanInstance( beanName, mbd, null );
				instance = bw.getWrappedInstance();
			}
		} catch (BeanCreationException ex) {
			// Can only happen when getting a FactoryBean.
			if (logger.isDebugEnabled()) {
				logger.debug( "Bean creation exception on non-singleton FactoryBean type check: " + ex );
			}
			onSuppressedException( ex );
			return null;
		} finally {
			// Finished partial creation of this bean.
			afterPrototypeCreation( beanName );
		}

		return getFactoryBean( beanName, instance );
	}

	/**
	 * Apply MergedBeanDefinitionPostProcessors to the specified bean definition,
	 * invoking their {@code postProcessMergedBeanDefinition} methods.
	 * 执行实现了MergedBeanDefinitionPostProcessor接口的后置处理器
	 *
	 * @param mbd      the merged bean definition for the bean
	 * @param beanType the actual type of the managed bean instance
	 * @param beanName the name of the bean
	 * @see MergedBeanDefinitionPostProcessor#postProcessMergedBeanDefinition
	 */
	protected void applyMergedBeanDefinitionPostProcessors(RootBeanDefinition mbd, Class<?> beanType, String beanName) {
		//执行合并 BeanDefinitionPostPRocessor
		for (BeanPostProcessor bp : getBeanPostProcessors()) {
			if (bp instanceof MergedBeanDefinitionPostProcessor) {
				MergedBeanDefinitionPostProcessor bdp = (MergedBeanDefinitionPostProcessor) bp;
				//执行后置处理器的postProcessMergedBeanDefinition方法
				bdp.postProcessMergedBeanDefinition( mbd, beanType, beanName );
			}
		}
	}

	/**
	 * Apply before-instantiation post-processors, resolving whether there is a
	 * before-instantiation shortcut for the specified bean.
	 *
	 * @param beanName the name of the bean
	 * @param mbd      the bean definition for the bean
	 * @return the shortcut-determined bean instance, or {@code null} if none
	 */
	@Nullable
	protected Object resolveBeforeInstantiation(String beanName, RootBeanDefinition mbd) {
		Object bean = null;
		if (!Boolean.FALSE.equals( mbd.beforeInstantiationResolved )) {
			// Make sure bean class is actually resolved at this point.
			if (!mbd.isSynthetic() && hasInstantiationAwareBeanPostProcessors()) {
				Class<?> targetType = determineTargetType( beanName, mbd );
				if (targetType != null) {
					bean = applyBeanPostProcessorsBeforeInstantiation( targetType, beanName );
					if (bean != null) {
						bean = applyBeanPostProcessorsAfterInitialization( bean, beanName );
					}
				}
			}
			mbd.beforeInstantiationResolved = (bean != null);
		}
		return bean;
	}

	/**
	 * Apply InstantiationAwareBeanPostProcessors to the specified bean definition
	 * (by class and name), invoking their {@code postProcessBeforeInstantiation} methods.
	 * <p>Any returned object will be used as the bean instead of actually instantiating
	 * the target bean. A {@code null} return value from the post-processor will
	 * result in the target bean being instantiated.
	 *
	 * @param beanClass the class of the bean to be instantiated
	 * @param beanName  the name of the bean
	 * @return the bean object to use instead of a default instance of the target bean, or {@code null}
	 * @see InstantiationAwareBeanPostProcessor#postProcessBeforeInstantiation
	 */
	@Nullable
	protected Object applyBeanPostProcessorsBeforeInstantiation(Class<?> beanClass, String beanName) {
		for (BeanPostProcessor bp : getBeanPostProcessors()) {
			if (bp instanceof InstantiationAwareBeanPostProcessor) {
				InstantiationAwareBeanPostProcessor ibp = (InstantiationAwareBeanPostProcessor) bp;
				Object result = ibp.postProcessBeforeInstantiation( beanClass, beanName );
				if (result != null) {
					return result;
				}
			}
		}
		return null;
	}

	/**
	 * 创建bean实例(返回包装类？)
	 * Create a new instance for the specified bean, using an appropriate instantiation strategy:
	 * factory method, constructor autowiring, or simple instantiation.
	 *
	 * @param beanName the name of the bean
	 * @param mbd      the bean definition for the bean
	 * @param args     explicit arguments to use for constructor or factory method invocation
	 * @return a BeanWrapper for the new instance
	 * @see #obtainFromSupplier
	 * @see #instantiateUsingFactoryMethod
	 * @see #autowireConstructor
	 * @see #instantiateBean
	 */
	protected BeanWrapper createBeanInstance(String beanName, RootBeanDefinition mbd, @Nullable Object[] args) {
		// Make sure bean class is actually resolved at this point.
		//解析Bean的Class对象
		Class<?> beanClass = resolveBeanClass( mbd, beanName );

		if (beanClass != null && !Modifier.isPublic( beanClass.getModifiers() ) && !mbd.isNonPublicAccessAllowed()) {
			throw new BeanCreationException( mbd.getResourceDescription(), beanName,
					"Bean class isn't public, and non-public access not allowed: " + beanClass.getName() );
		}

		//使用函数式接口获取对象
		Supplier<?> instanceSupplier = mbd.getInstanceSupplier();
		if (instanceSupplier != null) {
			return obtainFromSupplier( instanceSupplier, beanName );
		}
		//使用工厂方法实例化（如果使用@Bean方式注入，则注入方式为构造器注入）
		if (mbd.getFactoryMethodName() != null) {
			return instantiateUsingFactoryMethod( beanName, mbd, args );
		}

		// Shortcut when re-creating the same bean...
		/**
		 * 当多次构建同一个bean时，可以使用这个shortcut
		 * 也就是说不需要多次推断要使用哪种方式构造bean
		 * 比如早多次构建同一个prototype类型的bean时，就可以走此处的shortcut
		 * 这里的resolved和autowireNecessary将会在第一次实例化的过程中被设置
		 */
		boolean resolved = false;
		//是否要自动装配
		boolean autowireNecessary = false;
		if (args == null) {
			synchronized (mbd.constructorArgumentLock) {
				//resolvedConstructorOrFactoryMethod  使用构造器或者工厂方法解析
				if (mbd.resolvedConstructorOrFactoryMethod != null) {
					resolved = true;
					//构造器自动注入
					autowireNecessary = mbd.constructorArgumentsResolved;
				}
			}
		}
		//第一次是false
		if (resolved) {
			if (autowireNecessary) {
				//通过构造方法自动装配的方式构造bean对象
				return autowireConstructor( beanName, mbd, null, null );
			} else {
				//通过默认的无参构造器进行初始化
				return instantiateBean( beanName, mbd );
			}
		}

		// Candidate constructors for autowiring?
		//推断构造方法，由后置处理器决定返回哪些构造方法
		Constructor<?>[] ctors = determineConstructorsFromBeanPostProcessors( beanClass, beanName );
		if (ctors != null || mbd.getResolvedAutowireMode() == AUTOWIRE_CONSTRUCTOR ||
				mbd.hasConstructorArgumentValues() || !ObjectUtils.isEmpty( args )) {
			//如果推断结果为有构造器，则使用构造器自动注入方式
			return autowireConstructor( beanName, mbd, ctors, args );
		}

		// No special handling: simply use no-arg constructor.
		//没有显式写构造器，则使用默认无参构造器进行初始化
		return instantiateBean( beanName, mbd );
	}

	/**
	 * Obtain a bean instance from the given supplier.
	 *
	 * @param instanceSupplier the configured supplier
	 * @param beanName         the corresponding bean name
	 * @return a BeanWrapper for the new instance
	 * @see #getObjectForBeanInstance
	 * @since 5.0
	 */
	protected BeanWrapper obtainFromSupplier(Supplier<?> instanceSupplier, String beanName) {
		String outerBean = this.currentlyCreatedBean.get();
		this.currentlyCreatedBean.set( beanName );
		Object instance;
		try {
			instance = instanceSupplier.get();
		} finally {
			if (outerBean != null) {
				this.currentlyCreatedBean.set( outerBean );
			} else {
				this.currentlyCreatedBean.remove();
			}
		}
		BeanWrapper bw = new BeanWrapperImpl( instance );
		initBeanWrapper( bw );
		return bw;
	}

	/**
	 * Overridden in order to implicitly register the currently created bean as
	 * dependent on further beans getting programmatically retrieved during a
	 * {@link Supplier} callback.
	 *
	 * @see #obtainFromSupplier
	 * @since 5.0
	 */
	@Override
	protected Object getObjectForBeanInstance(
			Object beanInstance, String name, String beanName, @Nullable RootBeanDefinition mbd) {

		String currentlyCreatedBean = this.currentlyCreatedBean.get();
		if (currentlyCreatedBean != null) {
			registerDependentBean( beanName, currentlyCreatedBean );
		}

		return super.getObjectForBeanInstance( beanInstance, name, beanName, mbd );
	}

	/**
	 * Determine candidate constructors to use for the given bean, checking all registered
	 * {@link SmartInstantiationAwareBeanPostProcessor SmartInstantiationAwareBeanPostProcessors}.
	 *
	 * @param beanClass the raw class of the bean
	 * @param beanName  the name of the bean
	 * @return the candidate constructors, or {@code null} if none specified
	 * @throws org.springframework.beans.BeansException in case of errors
	 * @see org.springframework.beans.factory.config.SmartInstantiationAwareBeanPostProcessor#determineCandidateConstructors
	 */
	@Nullable
	protected Constructor<?>[] determineConstructorsFromBeanPostProcessors(@Nullable Class<?> beanClass, String beanName)
			throws BeansException {
		//InstantiationAwareBeanPostProcessors
		if (beanClass != null && hasInstantiationAwareBeanPostProcessors()) {
			for (BeanPostProcessor bp : getBeanPostProcessors()) {
				if (bp instanceof SmartInstantiationAwareBeanPostProcessor) {
					SmartInstantiationAwareBeanPostProcessor ibp = (SmartInstantiationAwareBeanPostProcessor) bp;
					Constructor<?>[] ctors = ibp.determineCandidateConstructors( beanClass, beanName );
					if (ctors != null) {
						return ctors;
					}
				}
			}
		}
		return null;
	}

	/**
	 * 默认无参构造器实例化Bean
	 * Instantiate the given bean using its default constructor.
	 *
	 * @param beanName the name of the bean
	 * @param mbd      the bean definition for the bean
	 * @return a BeanWrapper for the new instance
	 */
	protected BeanWrapper instantiateBean(final String beanName, final RootBeanDefinition mbd) {
		try {
			Object beanInstance;
			final BeanFactory parent = this;
			if (System.getSecurityManager() != null) {
				beanInstance = AccessController.doPrivileged( (PrivilegedAction<Object>) () ->
								getInstantiationStrategy().instantiate( mbd, beanName, parent ),
						getAccessControlContext() );
			} else {
				//得到类的实例化策略，默认情况下得到的是一个反射的实例化策略
				beanInstance = getInstantiationStrategy().instantiate( mbd, beanName, parent );
			}
			//获取bean实例后使用BeanWrapper包装
			BeanWrapper bw = new BeanWrapperImpl( beanInstance );
			//初始化包装对象(Bean实例属性填充、属性编辑)
			initBeanWrapper( bw );
			return bw;
		} catch (Throwable ex) {
			throw new BeanCreationException(
					mbd.getResourceDescription(), beanName, "Instantiation of bean failed", ex );
		}
	}

	/**
	 * Instantiate the bean using a named factory method. The method may be static, if the
	 * mbd parameter specifies a class, rather than a factoryBean, or an instance variable
	 * on a factory object itself configured using Dependency Injection.
	 *
	 * @param beanName     the name of the bean
	 * @param mbd          the bean definition for the bean
	 * @param explicitArgs argument values passed in programmatically via the getBean method,
	 *                     or {@code null} if none (-> use constructor argument values from bean definition)
	 * @return a BeanWrapper for the new instance
	 * @see #getBean(String, Object[])
	 */
	protected BeanWrapper instantiateUsingFactoryMethod(
			String beanName, RootBeanDefinition mbd, @Nullable Object[] explicitArgs) {

		return new ConstructorResolver( this ).instantiateUsingFactoryMethod( beanName, mbd, explicitArgs );
	}

	/**
	 * "autowire constructor" (with constructor arguments by type) behavior.
	 * Also applied if explicit constructor argument values are specified,
	 * matching all remaining arguments with beans from the bean factory.
	 * <p>This corresponds to constructor injection: In this mode, a Spring
	 * bean factory is able to host components that expect constructor-based
	 * dependency resolution.
	 *
	 * @param beanName     the name of the bean
	 * @param mbd          the bean definition for the bean
	 * @param ctors        the chosen candidate constructors
	 * @param explicitArgs argument values passed in programmatically via the getBean method,
	 *                     or {@code null} if none (-> use constructor argument values from bean definition)
	 * @return a BeanWrapper for the new instance
	 */
	protected BeanWrapper autowireConstructor(
			String beanName, RootBeanDefinition mbd, @Nullable Constructor<?>[] ctors, @Nullable Object[] explicitArgs) {

		return new ConstructorResolver( this ).autowireConstructor( beanName, mbd, ctors, explicitArgs );
	}

	/**
	 * Populate the bean instance in the given BeanWrapper with the property values
	 * from the bean definition.
	 *
	 * @param beanName the name of the bean
	 * @param mbd      the bean definition for the bean
	 * @param bw       the BeanWrapper with bean instance
	 */
	protected void populateBean(String beanName, RootBeanDefinition mbd, @Nullable BeanWrapper bw) {
		//bw bean的包装类
		if (bw == null) {
			if (mbd.hasPropertyValues()) {
				throw new BeanCreationException(
						mbd.getResourceDescription(), beanName, "Cannot apply property values to null instance" );
			} else {
				// Skip property population phase for null instance.
				return;
			}
		}

		/*
		 Give any InstantiationAwareBeanPostProcessors the opportunity to modify the
		 state of the bean before properties are set. This can be used, for example,
		 to support styles of field injection.
		 在属性设置之前给 InstantiationAwareBeanPostProcessors 后置处理器机会修改bean的状态
		 判断是否可以属性注入  ibp.postProcessAfterInstantiation()==false则不进行属性注入
		 mbd.isSynthetic():默认为false
		 */
		if (!mbd.isSynthetic() && hasInstantiationAwareBeanPostProcessors()) {
			for (BeanPostProcessor bp : getBeanPostProcessors()) {
				if (bp instanceof InstantiationAwareBeanPostProcessor) {
					InstantiationAwareBeanPostProcessor ibp = (InstantiationAwareBeanPostProcessor) bp;

					if (!ibp.postProcessAfterInstantiation( bw.getWrappedInstance(), beanName )) {
						return;
					}
				}
			}
		}
		//属性值（spring设置）
		PropertyValues pvs = (mbd.hasPropertyValues() ? mbd.getPropertyValues() : null);

		//解析自动注入模式（默认注入方式为no，不是byName也不是byType也不是ByConstructor）
		int resolvedAutowireMode = mbd.getResolvedAutowireMode();
		if (resolvedAutowireMode == AUTOWIRE_BY_NAME || resolvedAutowireMode == AUTOWIRE_BY_TYPE) {
			//ByName或者ByType---使用不可修改属性值对象
			MutablePropertyValues newPvs = new MutablePropertyValues( pvs );
			// Add property values based on autowire by name if applicable.
			if (resolvedAutowireMode == AUTOWIRE_BY_NAME) {
				//根据名称自动注入
				autowireByName( beanName, mbd, bw, newPvs );
			}
			// Add property values based on autowire by type if applicable.
			if (resolvedAutowireMode == AUTOWIRE_BY_TYPE) {
				//根据类型自动注入
				autowireByType( beanName, mbd, bw, newPvs );
			}
			pvs = newPvs;
		}

		//有InstantiationAwareBeanPostProcessors
		boolean hasInstAwareBpps = hasInstantiationAwareBeanPostProcessors();
		//需要判断引用中存在的引用 false
		boolean needsDepCheck = (mbd.getDependencyCheck() != AbstractBeanDefinition.DEPENDENCY_CHECK_NONE);

		if (hasInstAwareBpps || needsDepCheck) {
			if (pvs == null) {
				pvs = mbd.getPropertyValues();
			}
			//获取到get方法和set方法
			PropertyDescriptor[] filteredPds = filterPropertyDescriptorsForDependencyCheck( bw, mbd.allowCaching );
			if (hasInstAwareBpps) {
				//获取后置处理器
				for (BeanPostProcessor bp : getBeanPostProcessors()) {
					if (bp instanceof InstantiationAwareBeanPostProcessor) {
						InstantiationAwareBeanPostProcessor ibp = (InstantiationAwareBeanPostProcessor) bp;
						pvs = ibp.postProcessPropertyValues( pvs, filteredPds, bw.getWrappedInstance(), beanName );
						if (pvs == null) {
							return;
						}
					}
				}
			}
			if (needsDepCheck) {
				checkDependencies( beanName, mbd, filteredPds, pvs );
			}
		}

		if (pvs != null) {
			applyPropertyValues( beanName, mbd, bw, pvs );
		}
	}

	/**
	 * Fill in any missing property values with references to
	 * other beans in this factory if autowire is set to "byName".
	 *
	 * @param beanName the name of the bean we're wiring up.
	 *                 Useful for debugging messages; not used functionally.
	 * @param mbd      bean definition to update through autowiring
	 * @param bw       the BeanWrapper from which we can obtain information about the bean
	 * @param pvs      the PropertyValues to register wired objects with
	 */
	protected void autowireByName(
			String beanName, AbstractBeanDefinition mbd, BeanWrapper bw, MutablePropertyValues pvs) {

		String[] propertyNames = unsatisfiedNonSimpleProperties( mbd, bw );
		for (String propertyName : propertyNames) {
			if (containsBean( propertyName )) {
				Object bean = getBean( propertyName );
				pvs.add( propertyName, bean );
				registerDependentBean( propertyName, beanName );
				if (logger.isDebugEnabled()) {
					logger.debug( "Added autowiring by name from bean name '" + beanName +
							"' via property '" + propertyName + "' to bean named '" + propertyName + "'" );
				}
			} else {
				if (logger.isTraceEnabled()) {
					logger.trace( "Not autowiring property '" + propertyName + "' of bean '" + beanName +
							"' by name: no matching bean found" );
				}
			}
		}
	}

	/**
	 * Abstract method defining "autowire by type" (bean properties by type) behavior.
	 * <p>This is like PicoContainer default, in which there must be exactly one bean
	 * of the property type in the bean factory. This makes bean factories simple to
	 * configure for small namespaces, but doesn't work as well as standard Spring
	 * behavior for bigger applications.
	 *
	 * @param beanName the name of the bean to autowire by type
	 * @param mbd      the merged bean definition to update through autowiring
	 * @param bw       the BeanWrapper from which we can obtain information about the bean
	 * @param pvs      the PropertyValues to register wired objects with
	 * 根据类型自动注入
	 */
	protected void autowireByType(
			String beanName, AbstractBeanDefinition mbd, BeanWrapper bw, MutablePropertyValues pvs) {

		TypeConverter converter = getCustomTypeConverter();
		if (converter == null) {
			converter = bw;
		}

		Set<String> autowiredBeanNames = new LinkedHashSet<>( 4 );
		String[] propertyNames = unsatisfiedNonSimpleProperties( mbd, bw );
		for (String propertyName : propertyNames) {
			try {
				PropertyDescriptor pd = bw.getPropertyDescriptor( propertyName );
				// Don't try autowiring by type for type Object: never makes sense,
				// even if it technically is a unsatisfied, non-simple property.
				if (Object.class != pd.getPropertyType()) {
					MethodParameter methodParam = BeanUtils.getWriteMethodParameter( pd );
					// Do not allow eager init for type matching in case of a prioritized post-processor.
					boolean eager = !(bw.getWrappedInstance() instanceof PriorityOrdered);
					DependencyDescriptor desc = new AutowireByTypeDependencyDescriptor( methodParam, eager );
					Object autowiredArgument = resolveDependency( desc, beanName, autowiredBeanNames, converter );
					if (autowiredArgument != null) {
						pvs.add( propertyName, autowiredArgument );
					}
					for (String autowiredBeanName : autowiredBeanNames) {
						registerDependentBean( autowiredBeanName, beanName );
						if (logger.isDebugEnabled()) {
							logger.debug( "Autowiring by type from bean name '" + beanName + "' via property '" +
									propertyName + "' to bean named '" + autowiredBeanName + "'" );
						}
					}
					autowiredBeanNames.clear();
				}
			} catch (BeansException ex) {
				throw new UnsatisfiedDependencyException( mbd.getResourceDescription(), beanName, propertyName, ex );
			}
		}
	}


	/**
	 * Return an array of non-simple bean properties that are unsatisfied.
	 * These are probably unsatisfied references to other beans in the
	 * factory. Does not include simple properties like primitives or Strings.
	 *
	 * @param mbd the merged bean definition the bean was created with
	 * @param bw  the BeanWrapper the bean was created with
	 * @return an array of bean property names
	 * @see org.springframework.beans.BeanUtils#isSimpleProperty
	 */
	protected String[] unsatisfiedNonSimpleProperties(AbstractBeanDefinition mbd, BeanWrapper bw) {
		Set<String> result = new TreeSet<>();
		PropertyValues pvs = mbd.getPropertyValues();
		PropertyDescriptor[] pds = bw.getPropertyDescriptors();
		for (PropertyDescriptor pd : pds) {
			if (pd.getWriteMethod() != null && !isExcludedFromDependencyCheck( pd ) && !pvs.contains( pd.getName() ) &&
					!BeanUtils.isSimpleProperty( pd.getPropertyType() )) {
				result.add( pd.getName() );
			}
		}
		return StringUtils.toStringArray( result );
	}

	/**
	 * Extract a filtered set of PropertyDescriptors from the given BeanWrapper,
	 * excluding ignored dependency types or properties defined on ignored dependency interfaces.
	 *
	 * @param bw    the BeanWrapper the bean was created with
	 * @param cache whether to cache filtered PropertyDescriptors for the given bean Class
	 * @return the filtered PropertyDescriptors
	 * @see #isExcludedFromDependencyCheck
	 * @see #filterPropertyDescriptorsForDependencyCheck(org.springframework.beans.BeanWrapper)
	 * cache 默认为true
	 */
	protected PropertyDescriptor[] filterPropertyDescriptorsForDependencyCheck(BeanWrapper bw, boolean cache) {
		PropertyDescriptor[] filtered = this.filteredPropertyDescriptorsCache.get( bw.getWrappedClass() );
		if (filtered == null) {
			filtered = filterPropertyDescriptorsForDependencyCheck( bw );
			if (cache) {
				PropertyDescriptor[] existing =
						this.filteredPropertyDescriptorsCache.putIfAbsent( bw.getWrappedClass(), filtered );
				if (existing != null) {
					filtered = existing;
				}
			}
		}
		return filtered;
	}

	/**
	 * Extract a filtered set of PropertyDescriptors from the given BeanWrapper,
	 * excluding ignored dependency types or properties defined on ignored dependency interfaces.
	 *
	 * @param bw the BeanWrapper the bean was created with
	 * @return the filtered PropertyDescriptors
	 * @see #isExcludedFromDependencyCheck
	 */
	protected PropertyDescriptor[] filterPropertyDescriptorsForDependencyCheck(BeanWrapper bw) {
		List<PropertyDescriptor> pds = new ArrayList<>( Arrays.asList( bw.getPropertyDescriptors() ) );
		pds.removeIf( this::isExcludedFromDependencyCheck );
		return pds.toArray( new PropertyDescriptor[0] );
	}

	/**
	 * Determine whether the given bean property is excluded from dependency checks.
	 * <p>This implementation excludes properties defined by CGLIB and
	 * properties whose type matches an ignored dependency type or which
	 * are defined by an ignored dependency interface.
	 *
	 * @param pd the PropertyDescriptor of the bean property
	 * @return whether the bean property is excluded
	 * @see #ignoreDependencyType(Class)
	 * @see #ignoreDependencyInterface(Class)
	 */
	protected boolean isExcludedFromDependencyCheck(PropertyDescriptor pd) {
		return (AutowireUtils.isExcludedFromDependencyCheck( pd ) ||
				this.ignoredDependencyTypes.contains( pd.getPropertyType() ) ||
				AutowireUtils.isSetterDefinedInInterface( pd, this.ignoredDependencyInterfaces ));
	}

	/**
	 * Perform a dependency check that all properties exposed have been set,
	 * if desired. Dependency checks can be objects (collaborating beans),
	 * simple (primitives and String), or all (both).
	 *
	 * @param beanName the name of the bean
	 * @param mbd      the merged bean definition the bean was created with
	 * @param pds      the relevant property descriptors for the target bean
	 * @param pvs      the property values to be applied to the bean
	 * @see #isExcludedFromDependencyCheck(java.beans.PropertyDescriptor)
	 */
	protected void checkDependencies(
			String beanName, AbstractBeanDefinition mbd, PropertyDescriptor[] pds, PropertyValues pvs)
			throws UnsatisfiedDependencyException {

		int dependencyCheck = mbd.getDependencyCheck();
		for (PropertyDescriptor pd : pds) {
			if (pd.getWriteMethod() != null && !pvs.contains( pd.getName() )) {
				boolean isSimple = BeanUtils.isSimpleProperty( pd.getPropertyType() );
				boolean unsatisfied = (dependencyCheck == AbstractBeanDefinition.DEPENDENCY_CHECK_ALL) ||
						(isSimple && dependencyCheck == AbstractBeanDefinition.DEPENDENCY_CHECK_SIMPLE) ||
						(!isSimple && dependencyCheck == AbstractBeanDefinition.DEPENDENCY_CHECK_OBJECTS);
				if (unsatisfied) {
					throw new UnsatisfiedDependencyException( mbd.getResourceDescription(), beanName, pd.getName(),
							"Set this property value or disable dependency checking for this bean." );
				}
			}
		}
	}

	/**
	 * Apply the given property values, resolving any runtime references
	 * to other beans in this bean factory. Must use deep copy, so we
	 * don't permanently modify this property.
	 *
	 * @param beanName the bean name passed for better exception information
	 * @param mbd      the merged bean definition
	 * @param bw       the BeanWrapper wrapping the target object
	 * @param pvs      the new property values
	 */
	protected void applyPropertyValues(String beanName, BeanDefinition mbd, BeanWrapper bw, PropertyValues pvs) {
		if (pvs.isEmpty()) {
			return;
		}

		if (System.getSecurityManager() != null && bw instanceof BeanWrapperImpl) {
			((BeanWrapperImpl) bw).setSecurityContext( getAccessControlContext() );
		}

		MutablePropertyValues mpvs = null;
		List<PropertyValue> original;

		if (pvs instanceof MutablePropertyValues) {
			mpvs = (MutablePropertyValues) pvs;
			if (mpvs.isConverted()) {
				// Shortcut: use the pre-converted values as-is.
				try {
					bw.setPropertyValues( mpvs );
					return;
				} catch (BeansException ex) {
					throw new BeanCreationException(
							mbd.getResourceDescription(), beanName, "Error setting property values", ex );
				}
			}
			original = mpvs.getPropertyValueList();
		} else {
			original = Arrays.asList( pvs.getPropertyValues() );
		}

		TypeConverter converter = getCustomTypeConverter();
		if (converter == null) {
			converter = bw;
		}
		BeanDefinitionValueResolver valueResolver = new BeanDefinitionValueResolver( this, beanName, mbd, converter );

		// Create a deep copy, resolving any references for values.
		List<PropertyValue> deepCopy = new ArrayList<>( original.size() );
		boolean resolveNecessary = false;
		for (PropertyValue pv : original) {
			if (pv.isConverted()) {
				deepCopy.add( pv );
			} else {
				String propertyName = pv.getName();
				Object originalValue = pv.getValue();
				Object resolvedValue = valueResolver.resolveValueIfNecessary( pv, originalValue );
				Object convertedValue = resolvedValue;
				boolean convertible = bw.isWritableProperty( propertyName ) &&
						!PropertyAccessorUtils.isNestedOrIndexedProperty( propertyName );
				if (convertible) {
					convertedValue = convertForProperty( resolvedValue, propertyName, bw, converter );
				}
				// Possibly store converted value in merged bean definition,
				// in order to avoid re-conversion for every created bean instance.
				if (resolvedValue == originalValue) {
					if (convertible) {
						pv.setConvertedValue( convertedValue );
					}
					deepCopy.add( pv );
				} else if (convertible && originalValue instanceof TypedStringValue &&
						!((TypedStringValue) originalValue).isDynamic() &&
						!(convertedValue instanceof Collection || ObjectUtils.isArray( convertedValue ))) {
					pv.setConvertedValue( convertedValue );
					deepCopy.add( pv );
				} else {
					resolveNecessary = true;
					deepCopy.add( new PropertyValue( pv, convertedValue ) );
				}
			}
		}
		if (mpvs != null && !resolveNecessary) {
			mpvs.setConverted();
		}

		// Set our (possibly massaged) deep copy.
		try {
			bw.setPropertyValues( new MutablePropertyValues( deepCopy ) );
		} catch (BeansException ex) {
			throw new BeanCreationException(
					mbd.getResourceDescription(), beanName, "Error setting property values", ex );
		}
	}

	/**
	 * Convert the given value for the specified target property.
	 */
	@Nullable
	private Object convertForProperty(
			@Nullable Object value, String propertyName, BeanWrapper bw, TypeConverter converter) {

		if (converter instanceof BeanWrapperImpl) {
			return ((BeanWrapperImpl) converter).convertForProperty( value, propertyName );
		} else {
			PropertyDescriptor pd = bw.getPropertyDescriptor( propertyName );
			MethodParameter methodParam = BeanUtils.getWriteMethodParameter( pd );
			return converter.convertIfNecessary( value, pd.getPropertyType(), methodParam );
		}
	}


	/**
	 * Initialize the given bean instance, applying factory callbacks
	 * as well as init methods and bean post processors.
	 * <p>Called from {@link #createBean} for traditionally defined beans,
	 * and from {@link #initializeBean} for existing bean instances.
	 *
	 * @param beanName the bean name in the factory (for debugging purposes)
	 * @param bean     the new bean instance we may need to initialize
	 * @param mbd      the bean definition that the bean was created with
	 *                 (can also be {@code null}, if given an existing bean instance)
	 * @return the initialized bean instance (potentially wrapped)
	 * @see BeanNameAware
	 * @see BeanClassLoaderAware
	 * @see BeanFactoryAware
	 * @see #applyBeanPostProcessorsBeforeInitialization
	 * @see #invokeInitMethods
	 * @see #applyBeanPostProcessorsAfterInitialization
	 */
	protected Object initializeBean(final String beanName, final Object bean, @Nullable RootBeanDefinition mbd) {
		if (System.getSecurityManager() != null) {
			AccessController.doPrivileged( (PrivilegedAction<Object>) () -> {
				invokeAwareMethods( beanName, bean );
				return null;
			}, getAccessControlContext() );
		} else {
			//执行或者回调部分Aware方法
			invokeAwareMethods( beanName, bean );
		}

		Object wrappedBean = bean;
		if (mbd == null || !mbd.isSynthetic()) {
			//初始化前执行部分BeanPostProcessor的beanPostProcessorsBeforeInitialization方法
			//BeanPostProcessor#beanPostProcessorsBeforeInitialization方法在bean初始化之前执行
			wrappedBean = applyBeanPostProcessorsBeforeInitialization( wrappedBean, beanName );
		}

		try {
			//执行初始化方法
			invokeInitMethods( beanName, wrappedBean, mbd );
		} catch (Throwable ex) {
			throw new BeanCreationException(
					(mbd != null ? mbd.getResourceDescription() : null),
					beanName, "Invocation of init method failed", ex );
		}
		if (mbd == null || !mbd.isSynthetic()) {
			//初始化之后执行部分BeanPostProcessor的beanPostProcessorsAfterInitialization方法
			//BeanPostProcessor#beanPostProcessorsAfterInitialization方法在bean初始化之前执行
			//执行生成代理
			wrappedBean = applyBeanPostProcessorsAfterInitialization( wrappedBean, beanName );
		}

		return wrappedBean;
	}

	private void invokeAwareMethods(final String beanName, final Object bean) {
		if (bean instanceof Aware) {
			if (bean instanceof BeanNameAware) {
				((BeanNameAware) bean).setBeanName( beanName );
			}
			if (bean instanceof BeanClassLoaderAware) {
				ClassLoader bcl = getBeanClassLoader();
				if (bcl != null) {
					((BeanClassLoaderAware) bean).setBeanClassLoader( bcl );
				}
			}
			if (bean instanceof BeanFactoryAware) {
				((BeanFactoryAware) bean).setBeanFactory( AbstractAutowireCapableBeanFactory.this );
			}
		}
	}

	/**
	 * Give a bean a chance to react now all its properties are set,
	 * and a chance to know about its owning bean factory (this object).
	 * This means checking whether the bean implements InitializingBean or defines
	 * a custom init method, and invoking the necessary callback(s) if it does.
	 *
	 * @param beanName the bean name in the factory (for debugging purposes)
	 * @param bean     the new bean instance we may need to initialize
	 * @param mbd      the merged bean definition that the bean was created with
	 *                 (can also be {@code null}, if given an existing bean instance)
	 * @throws Throwable if thrown by init methods or by the invocation process
	 * @see #invokeCustomInitMethod
	 */
	protected void invokeInitMethods(String beanName, final Object bean, @Nullable RootBeanDefinition mbd)
			throws Throwable {

		boolean isInitializingBean = (bean instanceof InitializingBean);
		if (isInitializingBean && (mbd == null || !mbd.isExternallyManagedInitMethod( "afterPropertiesSet" ))) {
			if (logger.isDebugEnabled()) {
				logger.debug( "Invoking afterPropertiesSet() on bean with name '" + beanName + "'" );
			}
			if (System.getSecurityManager() != null) {
				try {
					AccessController.doPrivileged( (PrivilegedExceptionAction<Object>) () -> {
						((InitializingBean) bean).afterPropertiesSet();
						return null;
					}, getAccessControlContext() );
				} catch (PrivilegedActionException pae) {
					throw pae.getException();
				}
			} else {
				((InitializingBean) bean).afterPropertiesSet();
			}
		}

		if (mbd != null && bean.getClass() != NullBean.class) {
			String initMethodName = mbd.getInitMethodName();
			if (StringUtils.hasLength( initMethodName ) &&
					!(isInitializingBean && "afterPropertiesSet".equals( initMethodName )) &&
					!mbd.isExternallyManagedInitMethod( initMethodName )) {
				invokeCustomInitMethod( beanName, bean, mbd );
			}
		}
	}

	/**
	 * Invoke the specified custom init method on the given bean.
	 * Called by invokeInitMethods.
	 * <p>Can be overridden in subclasses for custom resolution of init
	 * methods with arguments.
	 *
	 * @see #invokeInitMethods
	 */
	protected void invokeCustomInitMethod(String beanName, final Object bean, RootBeanDefinition mbd)
			throws Throwable {

		String initMethodName = mbd.getInitMethodName();
		Assert.state( initMethodName != null, "No init method set" );
		final Method initMethod = (mbd.isNonPublicAccessAllowed() ?
				BeanUtils.findMethod( bean.getClass(), initMethodName ) :
				ClassUtils.getMethodIfAvailable( bean.getClass(), initMethodName ));

		if (initMethod == null) {
			if (mbd.isEnforceInitMethod()) {
				throw new BeanDefinitionValidationException( "Could not find an init method named '" +
						initMethodName + "' on bean with name '" + beanName + "'" );
			} else {
				if (logger.isDebugEnabled()) {
					logger.debug( "No default init method named '" + initMethodName +
							"' found on bean with name '" + beanName + "'" );
				}
				// Ignore non-existent default lifecycle methods.
				return;
			}
		}

		if (logger.isDebugEnabled()) {
			logger.debug( "Invoking init method  '" + initMethodName + "' on bean with name '" + beanName + "'" );
		}

		if (System.getSecurityManager() != null) {
			AccessController.doPrivileged( (PrivilegedAction<Object>) () -> {
				ReflectionUtils.makeAccessible( initMethod );
				return null;
			} );
			try {
				AccessController.doPrivileged( (PrivilegedExceptionAction<Object>) () ->
						initMethod.invoke( bean ), getAccessControlContext() );
			} catch (PrivilegedActionException pae) {
				InvocationTargetException ex = (InvocationTargetException) pae.getException();
				throw ex.getTargetException();
			}
		} else {
			try {
				ReflectionUtils.makeAccessible( initMethod );
				initMethod.invoke( bean );
			} catch (InvocationTargetException ex) {
				throw ex.getTargetException();
			}
		}
	}


	/**
	 * Applies the {@code postProcessAfterInitialization} callback of all
	 * registered BeanPostProcessors, giving them a chance to post-process the
	 * object obtained from FactoryBeans (for example, to auto-proxy them).
	 *
	 * @see #applyBeanPostProcessorsAfterInitialization
	 */
	@Override
	protected Object postProcessObjectFromFactoryBean(Object object, String beanName) {
		return applyBeanPostProcessorsAfterInitialization( object, beanName );
	}

	/**
	 * Overridden to clear FactoryBean instance cache as well.
	 */
	@Override
	protected void removeSingleton(String beanName) {
		synchronized (getSingletonMutex()) {
			super.removeSingleton( beanName );
			this.factoryBeanInstanceCache.remove( beanName );
		}
	}

	/**
	 * Overridden to clear FactoryBean instance cache as well.
	 */
	@Override
	protected void clearSingletonCache() {
		synchronized (getSingletonMutex()) {
			super.clearSingletonCache();
			this.factoryBeanInstanceCache.clear();
		}
	}

	/**
	 * Expose the logger to collaborating delegates.
	 *
	 * @since 5.0.7
	 */
	Log getLogger() {
		return logger;
	}


	/**
	 * Special DependencyDescriptor variant for Spring's good old autowire="byType" mode.
	 * Always optional; never considering the parameter name for choosing a primary candidate.
	 */
	@SuppressWarnings("serial")
	private static class AutowireByTypeDependencyDescriptor extends DependencyDescriptor {

		public AutowireByTypeDependencyDescriptor(MethodParameter methodParameter, boolean eager) {
			super( methodParameter, false, eager );
		}

		@Override
		public String getDependencyName() {
			return null;
		}
	}

}
